<?php 
/* YulMail API Class, By Olivier St-Laurent
 * Usage Example : 


    $yulmail = new YulMail("Username", "Password");
    
    if ($yulmail->connected) {
        
        $campaigns = $yulmail->fetchCampaigns();
        
        $newCampaignID = $yulmail->createCampaignEmailList('CampaignName', 'Subject', '<div>HTML Body</div>', "PlainTextBody", 'FromName', 'from@email.com', array(
            'to@email1.com',
            'to@email2.com',
            'to@email3.com',
        ));
        $yulmail->sendCampaign($newCampaignID);
        
    }


*/
class YulMail {
    protected $URL = 'https://yulmail.com/api.php';
    
    protected $connection = null;
    protected $sessionID  = null;
    protected $connected  = false;
    
    function __construct($username, $password, $alternativeUrl=null, array $params=array()) {
        $this->login($username, $password, $alternativeUrl, $params);
    }
    
    function login($username, $password, $alternativeUrl=null, array $params=array()) {
        if ($alternativeUrl !== null) {
            $this->URL = $alternativeUrl;
        }
        $this->connection = $this->request('User.Login', array(
            'Username'       => $username,
            'Password'       => $password,
            'DisableCaptcha' => 'false', 
        ), $params);
        if ($this->connection->Success) {
            $this->sessionID = $this->connection->SessionID;
            $this->connected = true;
        }
        return $this->connected;
    }
    
    function request($command, array $fields=array(), array $morefields=array()) {
        $fields = array_merge(array(
            'SessionID'      => $this->sessionID,
            'ResponseFormat' => 'JSON',
            'Command'        => $command,
        ), $fields, $morefields);
        foreach ($fields as $key=>$field) {
            if (!in_array($key, array(
                // UrlEncore All Except Those Keys
                'RecipientListsAndSegments', 
                'EmailAddress', 
                'FromName', 
                'FromEmail', 
                'ReplyToName', 
                'ReplyToEmail', 
                'Subject', 
                'HTMLContent', 
                'PlainContent', 
            ))) {
                $fields[$key] = urlencode($field);
            }
        }
        $content = http_build_query($fields);
        $ctx = stream_context_create(array(
            'http' => array(
                'method' => 'POST',
                'header' => "User-Agent: \r\n" .
                            "Accept-language: pt-br,pt;q=0.8,en-us;q=0.5,en;q=0.3\r\n" .
                            "Cookie: PHPSESSID=\r\n" . 
                            "Content-type: application/x-www-form-urlencoded; charset=UTF-8\r\n",
                'content' => $content,
                )
        ));
        $handle = fopen($this->URL, "rb", false, $ctx);
        $response = stream_get_contents($handle);
        fclose($handle);
        return json_decode($response);
    }
    
    public function setUrl($url) {
        $this->URL = $url;
    }
    public function getUrl() {
        return $this->URL;
    }
    
    public function isConnected() {
        return $this->connected;
    }
    
    public function getSessionID() {
        return $this->sessionID;
    }
    
    public function getConnection() {
        return $this->connection;
    }
    
    
    ////////////////////////////////////////////////////////////////
    // OemPro API Functions
    
    function createList($name, array $params=array()) {
        $newList = $this->request('List.Create', array(
            'SubscriberListName' => $name,
        ), $params);
        return $newList->Success? $newList->ListID : false;
    }
    function updateList($listID, array $params=array()) {
        return $this->request('List.Update', array(
            'ListID' => $listID,
        ), $params)->Success;
    }
    function fetchList($listID, array $params=array()){
        return $this->request('List.Get', array(
            'ListID'     => $listID,
        ), $params);
    }
    function fetchLists(array $params=array()){
        return $this->request('Lists.Get', array(
            'OrderField'     => 'Name',
            'OrderType'      => 'ASC',
        ), $params);
    }
    function deleteLists($IDs, array $params=array()){
        if (is_array($IDs)) {
            $IDs = implode(',', $IDs);
        }
        return $this->request('Lists.Delete', array(
            'Lists' => $IDs,
        ), $params)->Success;
    }
    function deleteList($ID, array $params=array()){
        return $this->deleteLists($ID, $params);
    }
    function newList($name, array $params=array()) {
        $newListID = $this->createList($name);
        $this->updateList($newListID, array_merge(array(
            'OptInMode' => 'Single',
        ), $params));
        return $newListID;
    }
    
    function createCampaign($name, array $params=array()) {
        $newCampaign = $this->request('Campaign.Create', array(
            'CampaignName' => $name,
        ), $params);
        return $newCampaign->Success? $newCampaign->CampaignID : false;
    }
    function updateCampaign($campaignID, array $params=array()) {
        return $this->request('Campaign.Update', array(
            'CampaignID' => $campaignID,
        ), $params)->Success;
    }
    function fetchCampaign($campaignID, array $params=array()) {
        return $this->request('Campaign.Get', array(
            'CampaignID'         => $campaignID,
            'RetrieveStatistics' => 'true',
        ), $params);
    }
    function fetchCampaigns(array $params=array()) {
        return $this->request('Campaigns.Get', array(
            'CampaignStatus' => 'All',
        ), $params);
    }
    function deleteCampaigns($IDs, array $params=array()){
        if (is_array($IDs)) {
            $IDs = implode(',', $IDs);
        }
        return $this->request('Campaigns.Delete', array(
            'Campaigns' => $IDs,
        ), $params)->Success;
    }
    function deleteCampaign($ID, array $params=array()){
        return $this->deleteCampaigns($ID, $params);
    }
    function newCampaign($name, $emailID, $listIDs, array $params=array()) {
        if (!is_array($listIDs)) {
            $listIDs = explode(',', $listIDs);
        }
        $lists = array();
        foreach ($listIDs as $list) {
            if (strpos($list, ':')===false) {
                $list .= ':0';
            }
            $lists[] = $list;
        }
        $lists = implode(',', $lists);
        $newCampaignID = $this->createCampaign($name);
        $this->updateCampaign($newCampaignID, array_merge(array(
            'RelEmailID' => $emailID,
            'RecipientListsAndSegments' => $lists,
        ), $params));
        return $newCampaignID;
    }
    function sendCampaign($campaignID, array $params=array()) {
        return $this->updateCampaign($campaignID, array_merge(array(
            'CampaignStatus' =>'Ready',
            'ScheduleType'   =>'Immediate',
        ), $params));
    }
    
    function createEmail(array $params=array()) {
        $newEmail = $this->request('Email.Create', $params);
        return $newEmail->Success? $newEmail->EmailID : false;
    }
    function updateEmail($emailID, array $params=array()) {
        return $this->request('Email.Update', array(
            'EmailID' => $emailID,
        ), $params)->Success;
    }
    function fetchEmail($emailID, array $params=array()) {
        return $this->request('Email.Get', array(
            'EmailID' => $emailID,
        ), $params);
    }
    function fetchEmails(array $params=array()) {
        return $this->request('Emails.Get', $params);
    }
    function deleteEmail($emailID, array $params=array()){
        return $this->request('Email.Delete', array(
            'EmailID' => $emailID,
        ), $params)->Success;
    }
    function newEmail($name, $subject, $bodyHTML, $bodyPlain, $fromName, $fromEmail, array $params=array()) {
        $newEmailID = $this->createEmail();
        $this->updateEmail($newEmailID, array_merge(array(
            'EmailName'      => $name,
            'FromName'       => $fromName,
            'FromEmail'      => $fromEmail,
            'ReplyToName'    => $fromName,
            'ReplyToEmail'   => $fromEmail,
            'Subject'        => $subject,
            'HTMLContent'    => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html><head></head><body>'. $bodyHTML . "\n<br /><br />\n<a id='unsubLink' href='%Link:Unsubscribe%'>Click here to unsubscribe</a></body></html>",
            'PlainContent'   => $bodyPlain . "\n\n%Link:Unsubscribe%",
            'Mode'           => 'Empty',
            'ImageEmbedding' => 'Disabled',
            'ValidateScope'  => 'Campaign',
        ), $params));
        return $newEmailID;
    }
    
    function createSubscriber($email, $listID, $IPAddress="0.0.0.0", array $params=array()) {
        $newSubscriber = $this->request('Subscriber.Subscribe', array(
            'EmailAddress' => $email,
            'ListID'       => $listID,
            'IPAddress'    => $IPAddress,
        ), $params);
        return $newSubscriber->Success? $newSubscriber->SubscriberID : false;
    }
    function updateSubscriber($subscriberID, array $params=array()) {
        return $this->request('Subscriber.Update', array(
            'SubscriberID' => $subscriberID,
        ), $params)->Success;
    }
    function fetchSubscriber($subscriberID, array $params=array()) {
        return $this->request('Subscriber.Get', array(
            'SubscriberID' => $subscriberID,
        ), $params);
    }
    function fetchSubscribers($listID, array $params=array()) {
        return $this->request('Subscribers.Get', array(
            'SubscriberListID' => $listID,
        ), $params);
    }
    function deleteSubscribers($IDs, $listID, array $params=array()){
        if (is_array($IDs)) {
            $IDs = implode(',', $IDs);
        }
        return $this->request('Subscribers.Delete', array(
            'Subscribers'      => $IDs,
            'SubscriberListID' => $listID,
        ), $params)->Success;
    }
    function deleteSubscriber($subscriberID, $listID, array $params=array()){
        return $this->request('Subscriber.Unsubscribe', array(
            (is_numeric($subscriberID)? 'SubscriberID':'EmailAddress') => $subscriberID,
            'SubscriberListID' => $listID,
        ), $params)->Success;
    }
    
    function createCampaignEmailList($name, $subject, $bodyHTML, $bodyPlain, $fromName, $fromEmail, array $toEmails=array(), array $campaignParams=array()) {
        $listID = $this->newList($name);
        foreach ($toEmails as $email) {
            if (is_array($email)) {
                $subscriberID = $this->createSubscriber($email['EmailAddress'], $listID, '0.0.0.0', $email);
            } else {
                $subscriberID = $this->createSubscriber($email, $listID, '0.0.0.0');
            }
        }
        $emailID = $this->newEmail($name, $subject, $bodyHTML, $bodyPlain, $fromName, $fromEmail);
        $campaignID = $this->newCampaign($name, $emailID, $listID, $campaignParams);
        return $campaignID;
    }
    
}